package com.system.boot.rbac.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.system.api.SuperInterface;
import com.system.api.rbac.entity.dto.MenuFormDto;
import com.system.api.rbac.entity.dto.RoleFormDto;
import com.system.api.rbac.entity.po.SysMenu;
import com.system.api.rbac.entity.po.SysRole;
import com.system.api.rbac.entity.search.RoleSearch;
import com.system.api.rbac.entity.vo.RoleListVo;
import com.system.boot.rbac.converter.RoleConverter;
import com.system.boot.rbac.service.RoleMenuService;
import com.system.boot.rbac.service.RolePermissionService;
import com.system.boot.rbac.service.RoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.yang.common.core.exception.BaseException;
import org.yang.common.core.result.BaseController;
import org.yang.common.core.result.R;
import org.yang.common.utils.jwt.JwtTokenAnalysisUtli;
import org.yang.database.orm.entity.BaseEnabled;
import org.yang.database.orm.entity.BaseQuery;
import org.yang.database.orm.entity.Options;

import java.sql.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 角色信息
 *
 * @author: lslands
 * @description:
 * @version：v1.0
 * @date: 2024/6/2 18:44
 */
@Slf4j
@RestController
@RequestMapping("/role")
@RequiredArgsConstructor
public class RoleController extends BaseController {

    private final RoleService roleService;
    private final RoleConverter roleConverter;
    private final RolePermissionService rolePermissionService;
    private final RoleMenuService roleMenuService;

    private final SuperInterface<SysRole> superInterface;


    /**
     * 新增/修改
     * @param dto 新增对象
     * @apiNote 通过是否存在主键,判定是新增还是修改;id为空则为新增，反之;
     * @author lslands
     * @date 2024/5/18 23:06
     * @return R<void>
     */
    @PostMapping("/saveOrUpdate")
    public R save(@RequestBody RoleFormDto dto) throws BaseException {
        SysRole record = roleConverter.formEntity(dto);
        return Objects.isNull(dto.getId())
                ? toCreateAjax(superInterface.handInsert(record))
                : toUpdateAjax(superInterface.handUpdateById(record));
    }

    /**
     * 更新状态
     * @param record 更新状态对象
     * @return R<void>
     */
    @PatchMapping("/updateStatus")
    public R updateStatus(@RequestBody BaseEnabled record) throws BaseException {
        return toUpdateAjax(
                superInterface.handEnabledById(record.getId(), record.getEnabled(), record.getRevision()));
    }

    /**
     * 单条数据查询
     * @param id 主键ID|1
     * @author lslands
     * @date 2024/5/19 23:05
     * @return SysRole
     */
    @GetMapping("/getById")
    public R<SysRole> getById(@RequestParam Long id){
        return R.success(roleService.getById(id));
    }

    /**
     * 分页模糊查询列表
     * @param search 分页查询参数
     * @return R<Page<SysMenu>>
     */
    @GetMapping("/page")
    public R<Page<SysRole>> page(@ModelAttribute RoleSearch search) throws BaseException {
        SysRole sysRole = roleConverter.queryPoEntity(search);
        BaseQuery query = roleConverter.queryEntity(search);
        return R.success(superInterface.getPage(query, sysRole));
    }

    /**
     * 角色列表
     * @return 角色列表
     * @throws BaseException 查询异常
     */
    @GetMapping("/listOptions")
    public R<List<Options<Integer>> > listOptions() throws BaseException {
        Long companyId = JwtTokenAnalysisUtli.companyId();
        List<String> roles = JwtTokenAnalysisUtli.roles();
        return R.success(roleService.listOptions(companyId,roles));
    }

    /**
     * 获取角色已绑定权限ID集合
     * @param roleId 角色ID
     * @apiNote 如果为指定超级角色,则返回为null; 因此直接通过前端判断，直接全选即可
     * @return 已绑定权限集
     */
    @GetMapping("/havePermIds")
    public R<List<Long>> havePermIdsByRole(@RequestParam("roleId") Long roleId) throws BaseException {
        return R.success(rolePermissionService.getPermissionsByRole(roleId));
    }

    /**
     * 获取菜单已绑定权限ID集合
     * @param roleId 角色ID
     * @apiNote 如果为指定超级角色,则返回为null; 因此直接通过前端判断，直接全选即可
     * @return 已绑定菜单集
     */
    @GetMapping("/haveMenuIds")
    public R<List<Long>> haveMenuIdsByRole(@RequestParam("roleId") Long roleId) throws BaseException {
        return R.success(roleMenuService.getMenusByRole(roleId));
    }

    /**
     * 分配权限
     * @param roleId 角色ID
     * @param permIds 权限ID集
     * @return 成功/失败
     * @throws BaseException 分配异常
     */
    @PatchMapping("/assignPermission/{roleId}")
    public R<?> assignPermission(@PathVariable("roleId") Long roleId,
                                 @RequestBody List<Long> permIds) throws BaseException {

        return R.success(rolePermissionService.assignPermission(roleId,permIds));
    }

    /**
     * 分配菜单
     * @param roleId 角色ID
     * @param menuIds 菜单ID集
     * @return 成功/失败
     * @throws BaseException 分配异常
     */
    @PatchMapping("/assignMenu/{roleId}")
    public R<?> assignMenu(@PathVariable("roleId") Long roleId,@RequestBody List<Long> menuIds) throws BaseException {
        return R.success(roleMenuService.assignMenus(roleId,menuIds));
    }

    /**
     * 单条逻辑删除
     * @param id 主键ID|1
     * @author lslands
     * @date 2024/5/19 22:28
     */
    @DeleteMapping("/deleteOne")
    public R deleteOne(@RequestBody Long id) throws BaseException {
        return toDeleteAjax(superInterface.deleteOne(id));
    }

    /**
     * 批量删除
     * @param ids 主键ID集|[1,2]
     * @param delete 是否物理删除标记|false
     * @author lslands
     * @date 2024/5/19 22:29
     */
    @DeleteMapping("/deleteBatch/{delete}")
    public R deleteBatch(@RequestBody List<Long> ids, @PathVariable("delete") Boolean delete) throws BaseException {
        return toDeleteAjax(superInterface.deleteBatch(delete,ids));
    }

}
